﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace BlogsAPI
{
    /// <summary>
    /// Перечисленные через запятую поля анкет, необходимые для получения. 
    /// Supported face attributes include age, gender, headPose, smile, facialHair, glasses and emotion.
    /// </summary>
    [Flags]
    public enum FaceFields
    {
        age = 1,
        gender = 2,
        headPose = 4,
        smile = 8,
        facialHair = 16,
        glasses = 32,
        emotion = 64,
    }

    /// <summary>
    /// Структура ответа на распознавание
    /// </summary>
    public struct FaceApiResult{
        public string JsonData;
        public HttpStatusCode Status;
        public int ResetInSeconds;
    }

    /// <summary>
    /// Определение данных по фото
    /// https://dev.projectoxford.ai/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236
    /// </summary>
    public class FaceApi
    {
        /// <summary>
        /// https://www.microsoft.com/cognitive-services/en-US/subscriptions
        /// </summary>
        private string _key = null;
        //https://westus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false
        //westeurope
        private const string detectUrl = "https://{1}.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes={0}";

        /// <summary>
        /// Класс для распознавания фоток
        /// </summary>
        /// <param name="key"></param>
        public FaceApi(string key)
        {
            _key = key;
        }

        /// <summary>
        /// Определение параметров и ответ в виде JSON
        /// </summary>
        /// <param name="url">Ссылка на картинку</param>
        /// <param name="fields">запрашиваемые поля</param>
        /// <param name="endpoint">зона точки API</param>
        /// <returns>[{"faceId":"9f94d6b5-4687-4c79-aff6-f964b4969b94","faceRectangle":{"top":46,"left":47,"width":76,"height":76},"faceAttributes":{"smile":0.033,"gender":"female","age":23.3,"facialHair":{"moustache":0.0,"beard":0.0,"sideburns":0.0},"glasses":"ReadingGlasses"}}]</returns>
        public FaceApiResult ProcessImage(string url, FaceFields? fields = null, String endpoint = "westcentralus")
        {
            if (String.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            FaceApiResult ret = new FaceApiResult()
            {
                Status = HttpStatusCode.OK,
                ResetInSeconds = 0,
                JsonData = String.Empty
            };
            try
            {
                string data = "{ \"url\":\"" + url + "\"}";
                string faceAtts = "age,gender,smile,facialHair,glasses";
                if(fields != null)
                {
                    faceAtts = (String.Join(",", fields.Value)).Replace(", ", ",");
                }
                using (var client = new WebClient())
                {
                    client.Headers.Set(HttpRequestHeader.ContentType, "application/json");
                    client.Headers.Add("Ocp-Apim-Subscription-Key", _key);
                    ret.JsonData = client.UploadString(String.Format(detectUrl, faceAtts, endpoint), data);
                }
            }
            catch(WebException webErr)
            {
                Debug.Write(webErr);
                if(webErr.Response is HttpWebResponse)
                {
                    //количество запросов превышено
                    ret.Status = (webErr.Response as HttpWebResponse).StatusCode;
                    if((webErr.Response as HttpWebResponse).Headers["Retry-After"] != null){
                        int.TryParse((webErr.Response as HttpWebResponse).Headers["Retry-After"], out ret.ResetInSeconds);
                    }
                }
            }
            catch (Exception e1)
            {
                Debug.Write(e1);
                ret.Status = HttpStatusCode.BadRequest;
            }
            return ret;
        }
    }
}
